package top.honlnk.czuan.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import top.honlnk.czuan.common.exception.CustomException;
import top.honlnk.czuan.mapper.PowerMapper;
import top.honlnk.czuan.pojo.entity.Power;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Slf4j
@Component
public class BitmaskUtil {
    // TODO 目前仅仅完成了 根据权限名获取权限值 的Redis缓存，后续再完善其他功能，Mapper中对应的方法是：
    @Autowired
    private PowerMapper powerMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    private static final String POWER_STRING_TO_VALUE = "powerStringToValue";


    /**
     * *********************
     * 判断是否拥有目标权限
     * *********************
     *
     * @param permissionValue  Integer 当前用户拥有的权限
     * @param targetPermission String 需要的权限
     */
    public void hasPermission(Integer permissionValue, String targetPermission) {
        Integer targetValue = getValueByName(targetPermission);
        hasPermission(permissionValue, targetValue);
    }

    /**
     * *******************
     * 判断是否拥有目标权限
     * *********************
     *
     * @param permissionList   Integer 当前用户拥有的权限
     * @param targetPermission List<String> 需要的权限列表
     */
    public void hasPermissionOfNames(Integer permissionList, List<String> targetPermission) {
        List<Integer> valueList = getValuesByNames(targetPermission);
        Integer value = valueListToValues(valueList);
        hasPermission(permissionList, value);
    }


    /**
     * *******************
     * 添加权限
     * *******************
     * 在已有的权限值上，根据传进来的一个字符串列表，并且返回新的权限值
     *
     * @param addPermissionList List<String>  要添加的权限（字符串列表）
     * @param powerValue        Integer 已拥有的权限（值），一般包含一个或多个权限
     * @return Integer 新的权限值
     */
    public Integer addPermissions(List<String> addPermissionList, Integer powerValue) {
        return combinePermissions(addPermissionList, powerValue);
    }

    /**
     * 获取权限值，有基础权限的时候：与添加权限功能一致，只是方法名不一样
     *
     * @param permissionList List<String> 要添加的权限（字符串列表）
     * @param powerValue     Integer 已拥有的权限（值），一般包含一个或多个权限
     * @return Integer  新的权限值
     */
    public Integer combinePermissions(List<String> permissionList, Integer powerValue) {
        List<Integer> values = getValuesByNames(permissionList);

        for (Integer value : values) {
            powerValue |= value;
        }
        return powerValue;
    }

    /**
     * *******************
     * 获取权限值：根据权限名获取权限值
     * *******************
     *
     * @param permissionList List<String> 要查询的权限（字符串列表）
     * @return Integer 权限值查询结果，一般包含一个或多个权限
     */
    public Integer combinePermissions(List<String> permissionList) {
        return combinePermissions(permissionList, 0);
    }

    /**
     * *******************
     * 删除权限
     * *******************
     *
     * @param delPermissionList List<String> 要删除的权限（字符串列表）
     * @param powerValue        Integer 已有的权限（值），一般包含一个或多个权限
     * @return Integer 新的权限值
     */
    public Integer delPermissions(List<String> delPermissionList, Integer powerValue) {
        List<Integer> delPermissionValues = getValuesByNames(delPermissionList);
        for (Integer delPermissionValue : delPermissionValues) {
            powerValue &= ~delPermissionValue;
        }
        return powerValue;
    }


    /**
     * 将权限名转换为权限值
     *
     * @param permission String
     * @return Integer
     */
    private Integer getValueByName(String permission) {
        List<Integer> powerValues = getValuesByNames(List.of(permission));
        if (powerValues.isEmpty()) {
            throw new CustomException("权限" + permission + "不合法");
        }
        return powerValues.get(0);

    }

    /**
     * 判断是否拥有目标权限
     *
     * @param permissionValue       Integer 当前用户拥有的权限
     * @param targetPermissionValue Integer 需要的权限
     * @throws CustomException 此账号无权执行该操作
     */
    public void hasPermission(Integer permissionValue, Integer targetPermissionValue) {
        if ((permissionValue & targetPermissionValue) != targetPermissionValue) {
            throw new CustomException("此账号无权执行该操作");
        }
    }


    /**
     * 根据权限名获取权限值
     *
     * @param permissionList List<String>  要查询的权限（字符串列表）
     * @return List<Integer> 查询结果：权限值列表
     */
    private @NotNull List<Integer> getValuesByNames(List<String> permissionList) {
        // 如果传入的权限列表为空，则返回一个空的权限值列表
        if (permissionList == null || permissionList.isEmpty()) {
            return Collections.emptyList();
        }

        // 1: 尝试从Redis获取值
        List<Object> redisKeys = new ArrayList<>(permissionList);
        List<Object> redisObjects = redisTemplate.opsForHash().multiGet(POWER_STRING_TO_VALUE, redisKeys);


        Map<String, Integer> redisValues = new HashMap<>();
        // 用Redis的非空结果填充redisValues
        for (int i = 0; i < permissionList.size(); i++) {
            String permission = permissionList.get(i);
            Object valueObject = redisObjects.get(i);
            if (valueObject != null) {
                // 假设Redis中存储的值是Integer或可以转换为Integer的数据
                redisValues.put(permission, (Integer) valueObject);
            } else {
                break;
            }
        }
        // 根据Redis结果将权限分为已找到和未找到列表
        Set<String> foundPermissions = redisValues.keySet();
        List<String> notFoundPermissions = permissionList.stream()
                .filter(p -> !foundPermissions.contains(p))
                .collect(Collectors.toList());

        // 2: 如果在Redis中找不到某些权限，那么就从数据库中查询
        List<Integer> dbValues;
        if (!notFoundPermissions.isEmpty()) {
            dbValues = powerMapper.selectValuesByNames(notFoundPermissions);
            if (dbValues != null && !dbValues.isEmpty()) {
                // 将新找到的值放入Redis
                Map<String, Integer> valuesToPut = IntStream.range(0, notFoundPermissions.size())
                        .boxed()
                        .collect(Collectors.toMap(notFoundPermissions::get, dbValues::get));
                redisTemplate.opsForHash().putAll(POWER_STRING_TO_VALUE, valuesToPut);

                // 将这些新值添加到redisValues以获得最终结果
                redisValues.putAll(valuesToPut);
            }
        }

        // 3: 按照与permissionList相同的顺序构建最终结果列表
        return permissionList.stream()
                .map(redisValues::get)
                .collect(Collectors.toList());
    }

    /**
     * 根据权限值列表获取权限信息列表
     *
     * @param permissionValues List<Integer>  要查询的权限（值列表）
     * @return List<Power> 查询结果：权限名列表（所有信息）
     */
    public List<Power> getPowerByValues(List<Integer> permissionValues) {
        return powerMapper.selectPowerByValues(permissionValues);
    }

    /**
     * 根据权限值获取权限名列表：根据一个值，将这个值包含的所有权限的权限信息查询出来
     *
     * @param permissionValue Integer  要查询的权限（值），一般包含一个或多个权限
     * @return List<Power>  查询结果：权限列表（所有信息）
     */
    public List<Power> getPowerByValue(Integer permissionValue) {
        return getPowerByValues(valuesToValueList(permissionValue));
    }

    /**
     * 根据权限值列表获取权限名列表
     *
     * @param permissionValues List<Integer> 要查询的权限（值列表）
     * @return List<String>  查询结果：权限名列表（与值列表是对应关系）
     */
    public List<String> getPowerNameByValues(List<Integer> permissionValues) {
        return powerMapper.selectNamesByValues(permissionValues);
    }

    /**
     * 根据权限值获取权限名列表
     *
     * @param permissionValue Integer 要查询的权限（值），一般包含一个或多个权限
     * @return List<String>  查询结果：权限名列表
     */
    public List<String> getPowerNameByValue(Integer permissionValue) {
        return getPowerNameByValues(valuesToValueList(permissionValue));
    }

    /**
     * 将权限值转换为权限值列表
     *
     * @param permissionValue Integer  要查询的权限（值），一般包含一个或多个权限
     * @return List<Integer>  查询结果：权限值列表
     */
    private @NotNull List<Integer> valuesToValueList(Integer permissionValue) {
        List<Integer> permissionValues = new ArrayList<>();
        int value = 1;

        while (value <= permissionValue) {
            if ((permissionValue & value) != 0) {
                permissionValues.add(value);
            }
            value = value << 1;
        }
        return permissionValues;
    }

    /**
     * 获取所有权限
     *
     * @return List<Power>
     */
    public List<Power> getAllPower() {
        return powerMapper.getAllPower();
    }

    /**
     * 获取所有权限名
     *
     * @return List<String>  查询数据库中所有权限名
     */
    public List<String> getAllPowerName() {
        return powerMapper.getAllPowerName();
    }
//    public List<String> getAllPowerName() {
//        return powerMapper.selectPowerNameByValues(getAllPower().stream().map(Power::getValue).toList());
//    }



    /**
     * 判断是否拥有目标权限
     *
     * @param permissionList       List<String> 当前用户拥有的权限
     * @param targetPermissionList List<String> 需要的权限
     */
    public void hasPermission(List<String> permissionList, List<String> targetPermissionList) {
        List<Integer> permissionValueList = getValuesByNames(permissionList);
        Integer permissionValues;
        permissionValues = valueListToValues(permissionValueList);

        List<Integer> targetPermissionValueList = getValuesByNames(targetPermissionList);
        Integer targetPermissionValues;
        targetPermissionValues = valueListToValues(targetPermissionValueList);
        hasPermission(permissionValues, targetPermissionValues);
    }

    /**
     * 判断是否拥有目标权限
     *
     * @param permissionList   List<String> 当前用户拥有的权限
     * @param targetPermission String 需要的权限
     */
    public void hasPermission(List<String> permissionList, String targetPermission) {
        List<Integer> permissionValueList = getValuesByNames(permissionList);
        Integer permissionValues;
        permissionValues = valueListToValues(permissionValueList);
        Integer targetValue = getValueByName(targetPermission);
        hasPermission(permissionValues, targetValue);
    }

    /**
     * 判断是否拥有目标权限
     *
     * @param permissionList        List<String>
     * @param targetPermissionValue Integer
     */
    public void hasPermissionValue(List<String> permissionList, Integer targetPermissionValue) {
        List<Integer> permissionValueList = getValuesByNames(permissionList);
        Integer permissionValues;
        permissionValues = valueListToValues(permissionValueList);
        hasPermission(permissionValues, targetPermissionValue);
    }


    /**
     * 判断是否拥有目标权限
     *
     * @param permissionList   Integer 当前用户拥有的权限
     * @param targetPermission List<Integer> 需要的权限列表
     */
    public void hasPermission(Integer permissionList, List<Integer> targetPermission) {
        Integer value = valueListToValues(targetPermission);
        hasPermission(permissionList, value);
    }


    /**
     * 将权限值列表转换为权限值
     *
     * @param permissionValues List<Integer>
     * @return Integer
     */
    private Integer valueListToValues(@NotNull List<Integer> permissionValues) {
        int value = 0;
        for (Integer permissionValue : permissionValues) {
            value |= permissionValue;
        }
        return value;
    }


    /**
     * 验证权限是否合法
     *
     * @param permissionList List<String>
     * @throws CustomException 权限（）不合法
     */
    public void verifyPermission(List<String> permissionList) {
        List<String> existPermissionList = powerMapper.findExistPermission(permissionList);
        Set<String> existPermissionSet = new HashSet<>(existPermissionList);

        for (String permission : permissionList) {
            if (!existPermissionSet.contains(permission)) {
                throw new CustomException("权限" + permission + "不合法");
            }
        }
    }

    /**
     * 验证权限是否合法
     *
     * @param permissionList List<Integer>
     * @throws CustomException 权限（）不合法
     */
    public void verifyPermissionValue(List<Integer> permissionList) {
        List<Integer> existPermissionList = powerMapper.findExistPermissionValues(permissionList);
        Set<Integer> existPermissionSet = new HashSet<>(existPermissionList);

        for (Integer permission : permissionList) {
            if (!existPermissionSet.contains(permission)) {
                throw new CustomException("权限" + permission + "不合法");
            }
        }
    }

    /**
     * 验证权限是否合法
     *
     * @param permissionValue Integer
     */
    public void verifyPermission(Integer permissionValue) {
        List<Integer> permissionValueList = valuesToValueList(permissionValue);
        verifyPermissionValue(permissionValueList);
    }
}
